package com.idas.service;

import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

import org.apache.log4j.Logger;

import com.idas.APIContext;
import com.idas.common.Util;
import com.idas.comp.*;
import com.idas.comp.enums.ResourceType;
import com.idas.comp.enums.Status;
import com.idas.db.ConnectionHandler;

@WebService
public class API {
	private static Logger logger = Logger.getLogger(API.class
			.getCanonicalName());

	public @WebResult(name = "resourcesList")
	List<? extends Resource> listResources(
			@WebParam(name = "uuid") String uuid,
			@WebParam(name = "resourceType") ResourceType type)
			throws RemoteException {
		List<? extends Resource> resourceList = new ArrayList<Resource>();
		Connection conn = null;
		try {
			conn = ConnectionHandler.getClusterConnection();
			UserAccess uac = getUAC();

			switch (type) {
			case USER:
				resourceList = User.getUserListForUUID(conn, uuid, uac);
				break;
			case MODULE:
				resourceList = Module.getModuleListForUUID(conn, uuid, uac);
				break;
			case EXPENSE:
				break;
			default:
				break;
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in listResources ");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, false);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return resourceList;
	}

	public @WebResult(name = "countryList")
	List<Country> listCountries() throws RemoteException {
		List<Country> list = new ArrayList<Country>();
		Connection conn = null;
		try {
			conn = ConnectionHandler.getClusterConnection();
			list = Country.getAllCountries(conn);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in listResources ");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, false);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return list;
	}

	public @WebResult(name = "user")
	User createUser(@WebParam(name = "user") User user, String password)
			throws RemoteException {
		User nUser = new User();
		Connection conn = null;
		boolean commit = false;
		try {
			conn = ConnectionHandler.getClusterConnection();
			UserAccess uac = getUAC();
			UserPermissions perm = uac.getPermissions();

			if (!perm.isCreateUser()) {
				throw new Exception("Permisson denied");
			}
			nUser = User.createUser(conn, user, password);
			commit = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in createUser ");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, commit);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return nUser;
	}

	public @WebResult(name = "user")
	User modifyUser(@WebParam(name = "user") User updatedUser,
			@WebParam(name = "new_password") String password)
			throws RemoteException {
		Connection conn = null;
		boolean commit = false;
		User currUser = null;
		try {
			conn = ConnectionHandler.getClusterConnection();
			UserAccess uac = getUAC();
			UserPermissions perm = uac.getPermissions();

			if (uac.getUser().getUuid().equalsIgnoreCase(updatedUser.getUuid())) {
				perm.setModifyUser(true);
			}

			if (!perm.isModifyUser()) {
				throw new Exception("Permisson denied");
			}

			currUser = User.getUserForUUID(conn, updatedUser.getUuid());

			if (null == currUser) {
				throw new Exception("Failed to find User");
			}

			currUser.modifyUser(conn, updatedUser);

			if (Util.isNotNull(password)) {
				currUser.setPassword(conn, password);
			}

			if (uac.getUser().getStatus() == Status.ADMIN) {
				if (currUser.getStatus() != updatedUser.getStatus()) {
					currUser.setStatus(conn, updatedUser.getStatus());
				}

				if (currUser.getSignedOath() != updatedUser.getSignedOath()) {
					currUser.setSignedOath(conn, updatedUser.getSignedOath());
				}

				if (currUser.getCanUKWork() != updatedUser.getCanUKWork()) {
					currUser.setCanUKWork(conn, updatedUser.getCanUKWork());
				}
			}

			commit = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in modifyUser ");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, commit);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return currUser;
	}

	public @WebResult(name = "module")
	Module createModule(@WebParam(name = "module") Module module)
			throws RemoteException {
		Module nModule = new Module();
		Connection conn = null;
		boolean commit = false;
		try {
			conn = ConnectionHandler.getClusterConnection();
			UserAccess uac = getUAC();
			UserPermissions perm = uac.getPermissions();

			if (!perm.isCreateModule()) {
				throw new Exception("Permisson denied");
			}

			nModule = Module.createModule(conn, nModule, uac.getUserId());
			commit = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in createModule");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, commit);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return nModule;
	}

	public @WebResult(name = "module")
	Module modifyModule(@WebParam(name = "module") Module updatedModule)
			throws RemoteException {
		Connection conn = null;
		boolean commit = false;
		Module currModule = null;
		try {
			conn = ConnectionHandler.getClusterConnection();
			UserAccess uac = getUAC();
			UserPermissions perm = uac.getPermissions();

			currModule = Module.getModuleForUUID(conn, updatedModule.getUuid());

			if (null == currModule) {
				throw new Exception("Unable to find module");
			}

			if (currModule.isOwner(conn, uac.getUserId())) {
				perm.setModifyModule(true);
			}

			if (!perm.isModifyModule()) {
				throw new Exception("Permisson denied");
			}

			currModule.modifyModule(conn, updatedModule);

			commit = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in modifyModule");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, commit);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return currModule;
	}

	public @WebResult(name = "expense")
	Expense createExpense(@WebParam(name = "expense") Expense exp)
			throws RemoteException {
		Connection conn = null;
		boolean commit = false;
		Expense nExp = null;
		try {
			conn = ConnectionHandler.getClusterConnection();
			UserAccess uac = getUAC();
			nExp = Expense.createExpense(conn, uac, exp);
			commit = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in createExpense");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, commit);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return nExp;
	}

	public @WebResult(name = "success")
	Boolean deleteResource(@WebParam(name = "uuid") String uuid)throws RemoteException {
		Connection conn = null;
		boolean commit = false;
		
		try {
			conn = ConnectionHandler.getClusterConnection();
			UserAccess uac = getUAC();
			
			if(uac.getUser().getStatus()!= Status.ADMIN){
				throw new Exception("Permisson denied");
			}
			
			Resource res = Resource.getResourceForUUID(conn, uuid);
			
			if(null==res){
				throw new Exception("Unable to find resource");
			}
			
			res.delete(conn);
			
			commit = true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RemoteException("Exception in createExpense");
		} finally {
			try {
				ConnectionHandler.endConnection(conn, commit);
			} catch (SQLException e) {
				logger.error(e);
				e.printStackTrace();
			}
		}
		return commit;
	}

	protected UserAccess getUAC() {
		return (UserAccess) APIContext.getCurrentContext().getObject(
				APIContext.AUTH_USER_KEY);
	}

}
